#!/usr/bin/env python3
import pika
import time
import os
import json
from subprocess import Popen, PIPE
import sqlite3
import sys
import getUrlfile
from PIL import Image

#downloadUrlTryTimes = 10 # if download url err, try 100 times
#downloadTryDict = {}

def callback_getcommand(ch, method, properties, body):
    '''
    input: message from passDB manager
    output: message to DBImgQueue
    '''
    global downloadTryDict
    errcode = 0
    print(" [x] Received %r" % body)
    msg = str(body, 'utf-8')

    msgdict = json.loads(msg)
    operate = msgdict.get("operate")
    url = msgdict.get("url")
    faceid = msgdict.get("faceid")

    if operate == "face_add":
        # download url to local jpg file
        for k in range(5):
            localtmpjpgpath = "../EP_imgTmpSpace/" + str(time.time()) + ".jpg"
            try:
                getUrlfile.requestImg(url, localtmpjpgpath)
                errcode = 0
            except:
                errcode = 1
                #print(url, "err! resource can't be download. err!")
                #ch.basic_ack(delivery_tag = method.delivery_tag)

            for i in range(10):
                try:
                    img = Image.open(localtmpjpgpath)
                    wid = img.width
                    if wid > 0:
                        break
                    else:
                        time.sleep(0.5)
                except:
                    time.sleep(0.5)

        ch.basic_ack(delivery_tag = method.delivery_tag)
        '''if not os.path.exists(localtmpjpgpath):
            print("err! resource can't be download. err! try once more. the url: ", url)
            errcode = 1

        if errcode == 1:
            if url in downloadTryDict:
                downloadTryDict[url] -= 1
                if downloadTryDict[url] > 0:
                    ch.queue_declare(queue='PDMoutQueue')
                    channel.basic_publish(exchange='', routing_key='PDMoutQueue', body=body)
                else:
                    print("Sorry! resource can't be download after 100 times try. the url: ", url)
            else:
                downloadTryDict.update({url:downloadUrlTryTimes})'''
        
        if errcode == 0:
            '''if url in downloadTryDict:
                downloadTryDict.pop({url})'''

            # 生成img to face feature vector调用指令消息内容,发布消息
            dict = {}
            dict.update({'localtmpjpgpath':localtmpjpgpath})
            dict.update({'faceid':faceid})
            dict.update({'operate':operate})
            commandmsg = json.dumps(dict)

            ch.basic_publish(exchange='', routing_key='DbImgpathQueue', body=commandmsg)
            print("msg: ", commandmsg)
            print(" [x] Sent msg out!")

            ch.basic_ack(delivery_tag = method.delivery_tag)
    elif operate == "face_del": # notice: this del a person's all photos 
        dict = {}
        dict.update({'faceid':faceid})
        dict.update({'operate':operate})
        dict.update({'facefeature':[]})
        commandmsg = json.dumps(dict)

        ch.basic_publish(exchange='', routing_key='DbVecQueue', body=commandmsg)
        print("msg: ", commandmsg)
        print(" [x] Sent msg out!")

        ch.basic_ack(delivery_tag = method.delivery_tag)
    else:
        print("db operate command format err.")
        ch.basic_ack(delivery_tag = method.delivery_tag)


def callback_operateFaceDB(ch, method, properties, body):
    '''
    input: face feature vector
    output: insert face feature vector to db
    '''
    start = time.time()
    print(" [x] Received %r" % body)
    msg = str(body, 'utf-8')
    dict = json.loads(msg)
    faceid = dict["faceid"]
    operate = dict["operate"]
    facefeature = dict["facefeature"]

    con = sqlite3.connect("../EP_faceDB/faceiddatabase.db3")
    cur = con.cursor()
    try:
        cur.execute('CREATE TABLE facedb(face_id TEXT PRIMARY KEY, face_featurevector TEXT)')
        con.commit()
    except:
        print("db is already exists.")

    ifdbchanged = 0 
    curfaceid = str(faceid)
    curfacevec = str(facefeature)
    curoption = str(operate)

    # add face
    if curoption == "face_add":
        try:
            cur.execute("SELECT * FROM facedb WHERE face_id = '%s'" % curfaceid)
            output = cur.fetchall()
            if len(output) >= 5:
                print("current faceid has more than 5 faces already.")
                #continue
                return
        except:
            print("select facedb err.")

        try:
            cur.execute("INSERT INTO facedb(face_id, face_featurevector) VALUES('%s', '%s')" % (curfaceid, curfacevec))
            con.commit()
            ifdbchanged = 1
        except:
            print("current face id is already exists.")

    # del all faces of a person
    if curoption == "face_del":
        try:
            cur.execute("DELETE FROM facedb WHERE face_id = '%s'" % curfaceid)
            con.commit()
            ifdbchanged = 1
        except:
            print("current person/faceid is not found.")
    con.close()

    # if face db changed, face recognition module should reload db
    if ifdbchanged:
        tmpqueue = channel.queue_declare(queue='DbReloadQueue')
        msgcount = tmpqueue.method.message_count
        print("msg count in DbReloadQueue is :", msgcount)

        if msgcount == 0:
            commandmsg = "reload face db"
            ch.basic_publish(exchange='', routing_key='DbReloadQueue', body=commandmsg)
            print("msg: ", commandmsg)
            print(" [x] Sent msg out!")

    ch.basic_ack(delivery_tag = method.delivery_tag)
    end = time.time()
    print("time cost: ", end - start)


if __name__ == '__main__':
    '''
    发布img imgpath指令至rabbitMQ服务器
    '''
    # 建立连接
    credentials = pika.PlainCredentials('aiot', 'aiot')
    Parameter = pika.ConnectionParameters('127.0.0.1', 5672, '/', credentials)
    connection = pika.BlockingConnection(Parameter)
    channel = connection.channel()

    # 声明/指定消息队列
    channel.queue_declare(queue='DbImgpathQueue')
    channel.queue_declare(queue='DbVecQueue')
    channel.queue_declare(queue='DbReloadQueue')
    channel.queue_declare(queue='PDMoutQueue')

    # 配置从rabbitMQ服务器消息队列中取消息的参数
    channel.basic_consume(queue='PDMoutQueue', on_message_callback=callback_getcommand)
    channel.basic_consume(queue='DbVecQueue', on_message_callback=callback_operateFaceDB)

    # 永久持续运行
    print(' [*] Waiting for messages. To exit press CTRL+C')
    channel.start_consuming()

